package opengl.program;

import java.nio.FloatBuffer;

import math.MatrixUtil;

import org.lwjgl.opengl.GL20;

import world.Camera;
import world.WorldManager;

public class GLProgramManager {
	public static GLProgramManager get() {
		if (instance == null) {
			instance = new GLProgramManager();
		}
		return instance;
	}

	// ----------------------------------------------------------------private
	private static GLProgramManager instance;
	private WorldManager worldManager;
	private BaseGLProgram baseProgram;
	private BlockGLProgram blockProgram;
	private LineGLProgram lineGLProgram;

	private GLProgramManager() {
	}

	public void init() throws Exception {
		worldManager = WorldManager.get();
		
		baseProgram = new BaseGLProgram();
		baseProgram.init();

		lineGLProgram = new LineGLProgram();
		lineGLProgram.init();

		blockProgram = new BlockGLProgram();
		blockProgram.init();
	}

	public void resized(int width, int height) {
		Camera camera = worldManager.getCamera();
		FloatBuffer projectionMatrixBuffer = MatrixUtil.toBuffer(worldManager.getCamera().getProjectionMatrix());

		baseProgram.begin();
		{
			GL20.glUniformMatrix4(baseProgram.getProjectionMatrixUniform(), false, projectionMatrixBuffer);
		}
		baseProgram.end();

		lineGLProgram.begin();
		{
			GL20.glUniformMatrix4(lineGLProgram.getProjectionMatrixUniform(), false, projectionMatrixBuffer);
			GL20.glUniformMatrix4(lineGLProgram.getCameraMatrixUniform(), false, camera.calcLookAtMatrix().toBuffer());

		}
		lineGLProgram.end();

		blockProgram.begin();
		{
			GL20.glUniformMatrix4(blockProgram.getProjectionMatrixUniform(), false, projectionMatrixBuffer);
			GL20.glUniformMatrix4(blockProgram.getCameraMatrixUniform(), false, camera.calcLookAtMatrix().toBuffer());
		}
		blockProgram.end();
	}

	public BlockGLProgram getBlockProgram() {
		return blockProgram;
	}

	public BaseGLProgram getBaseProgram() {
		return baseProgram;
	}

	public LineGLProgram getLineProgram() {
		return lineGLProgram;
	}
}
